﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using epk23.PartIIProject.Exceptions;
using System.Windows;

namespace epk23.PartIIProject
{
    static class FileManager
    {
        static String folderName = "C:\\Machines\\";

        public static MachineLayout readFile(String machineName)
        {
            Machine m = new Machine();
            List<int[]> layout = new List<int[]>();

            String fileName = folderName + machineName + ".regm";
            TextReader tr = new StreamReader(fileName);

            String currentLine = tr.ReadLine();

            while (currentLine != "--")
            {
                readRule(m, currentLine);
                currentLine = tr.ReadLine();
            }

            m.startRuleNumber = Int32.Parse(tr.ReadLine());
            currentLine = tr.ReadLine();

            currentLine = tr.ReadLine();
            while (currentLine != "")
            {
                String[] posArray = currentLine.Split(' ');
                int[] intPosArray = new int[posArray.Length];
                int i = 0;
                foreach (string s in posArray)
                {
                    intPosArray[i] = Int32.Parse(posArray[i]);
                    i++;
                }

                layout.Add(intPosArray);
                currentLine = tr.ReadLine();
            }
            tr.Close();

            return new MachineLayout(m, layout);
        }


        public static void writeFile(MachineGraph graph, string machineName)
        {
            Machine m = graph.machine;

            TextWriter tw = new StreamWriter(folderName + machineName + ".regm");

            foreach (Rule r in m.rules)
            {
                String rulestring = r.ruleNumber + " ";

                if (r.GetType() == typeof(HaltRule))
                {
                    rulestring += "H";
                }
                else if (r.GetType() == typeof(IncrementRule))
                {
                    rulestring += "I " + r.targetRegister + " " + ((IncrementRule)r).targetRuleNumber;
                }
                else if (r.GetType() == typeof(DecrementRule))
                {
                    rulestring += "D " + r.targetRegister + " " + ((DecrementRule)r).targetRuleNumber + " " + ((DecrementRule)r).targetRuleNumber2;
                }
                else if (r.GetType() == typeof(MachineRule))
                {
                    rulestring += "M " + ((MachineRule)r).machineName + " " + ((MachineRule)r).targetRuleNumber;
                }

                tw.WriteLine(rulestring);
            }

            tw.WriteLine("--");

            tw.WriteLine(m.startRuleNumber);

            tw.WriteLine("--");


            foreach (RuleNode node in graph.nodes)
            {
                tw.WriteLine(((ConcreteNode)node).getRule().ruleNumber + " " + node.x + " " + node.y);
            }

            tw.WriteLine("");
            tw.Close();
        }

        private static void readRule(Machine m, String s)
        {
            String[] ruleArray = s.Split(' ');

            String ruleType = ruleArray[1];
            int ruleNumber = Int32.Parse(ruleArray[0]);

            if (ruleType == "H") //rule is a halt
            {
                m.addRule(new HaltRule(ruleNumber));
            }
            else if (ruleType == "I")
            {
                m.addRule(new IncrementRule(ruleNumber, ruleArray[2], Int32.Parse(ruleArray[3])));
            }
            else if (ruleType == "D")
            {
                m.addRule(new DecrementRule(ruleNumber, ruleArray[2], Int32.Parse(ruleArray[3]), Int32.Parse(ruleArray[4])));
            }
            else if (ruleType == "M")
            {
                m.addRule(new MachineRule(ruleNumber, ruleArray[2], Int32.Parse(ruleArray[3])));
            }
            else throw new InvalidRuleTypeException();
        }
    }

    class MachineLayout
    {
        private Machine machine;
        public Machine Machine
        { get { return machine; } }

        private List<int[]> layout;
        public List<int[]> Layout
        { get { return layout; } }

        public MachineLayout(Machine m, List<int[]> layout)
        {
            this.machine = m;
            this.layout = layout;
        }

        public Point getPosition(int ruleNumber)
        {
            Point position = new Point();
            foreach (int[] posArray in layout)
            {
                if (posArray[0] == ruleNumber)
                {
                    position.X = posArray[1];
                    position.Y = posArray[2];
                    break;
                }

            }
            return position;
        }
    }
}